//给你一个整数数组 nums ，除某个元素仅出现 一次 外，其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。 
//
// 
//
// 示例 1： 
//
// 
//输入：nums = [2,2,3,2]
//输出：3
// 
//
// 示例 2： 
//
// 
//输入：nums = [0,1,0,1,0,1,100]
//输出：100
// 
//
// 
//
// 提示： 
//
// 
// 1 <= nums.length <= 3 * 10⁴ 
// -2³¹ <= nums[i] <= 2³¹ - 1 
// nums 中，除某个元素仅出现 一次 外，其余每个元素都恰出现 三次 
// 
//
// 
//
// 进阶：你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗？ 
//
// 
//
// 注意：本题与主站 137 题相同：https://leetcode-cn.com/problems/single-number-ii/ 
// Related Topics 位运算 数组 👍 9 👎 0


package leetcode.editor.cn1;

//Java：只出现一次的数字
public class WGki4K {
    public static void main(String[] args) {
        Solution solution = new WGki4K().new Solution();
        // TO TEST
        System.out.println(solution.singleNumber(new int[]{0,1,0,1,0,1,100}));
    }

    //leetcode submit region begin(Prohibit modification and deletion)
    class Solution {
        // 某个元素出现1次之外，其余元素都出现3次
        public int singleNumber(int[] nums) {
            // 从32位角度考虑问题，一个int占用32位
            // 先计算一下数组中每个数的第i位的和
            int[] sumAttr = new int[32];
            for (int i = 0; i < 32; i++) {
                int sum = 0;
                for (int j = 0; j < nums.length; j++) {
                    // 注意位移的优先级
                    // 获取第i位数字是1还是0 nums[j] >> (31 - i)
                    sum = sum + ((nums[j] >> (31 - i)) & 1);
                }
                sumAttr[i] = sum;
            }

            int result = 0;
            for (int i = 0; i < 32; i++) {
                if (sumAttr[i] % 3 == 0) {
                    // 当前位是0
                    // 单独对某一位进行赋值
                    result = result << 1;
                } else {
                    // 当前位是1
                    result = (result << 1) + 1;
                }
            }
            return result;
        }
    }
//leetcode submit region end(Prohibit modification and deletion)

}
